#ifndef DATASTRUCTURES_H
#define DATASTRUCTURES_H
#include <vector>
#include <math.h>

class Triangle;
class Edge;

class ControlValue
{
public:
    double s;
    ControlValue():s(0){}

    static double min;
    static double max;
    static double avg;
};

struct Velocity
{
    double x;
    double y;
    Velocity() {x = 0; y= 0;}
};

class Point
{
public:
    double x;
    double y;
    int index;
    double param;

    double omega;
    double psi;
    double temp;
    Velocity v;


    double new_psi;
    double new_omega;
    std::vector <Triangle *> triangles;
    std::vector <Edge *> edges;
    ControlValue cv;

    Point(double x, double y, double param, int index) { this->x = x; this->y = y; this->param = param; this->index = index;}
    Point() {}
};

class Triangle
{
public:
    double area();
    double calculateArea();

    Point * next_point(Point *rel_p);
    Point * prev_point(Point *rel_p);
    double avg_psi() {return (p1->psi+p2->psi+p3->psi)/3.0;}

    Point center();

    Point *p1;
    Point *p2;
    Point *p3;

    std::vector <Edge* > edges;

    int index;
    int param;

    Triangle(Point *p1, Point *p2, Point *p3, int index, int param =0)
    {
        this->param = param;
        this->p1 = p1;
        this->p2 = p2;
        this->p3 = p3;
        this->index = index;
        this->area_ = calculateArea();
    }

    Edge *getEdge(Point *p1, Point *p2);

    Triangle(){}

private:
    double area_;

};

class Edge
{
public:
    enum EDGE_TYPE {NONE, WALL, IN, OUT};
    Edge(Point *p1, Point *p2) {this->p1 = p1; this->p2 = p2; type = NONE; length_ = calcLenght();}
    bool isBorder() { return (type == WALL) || (type == IN) || (type == OUT); }
    double length() {return length_;}
    double calcLenght() {return sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y) );}
    double avg_omega() {return ((p1->omega+p2->omega)/2.0);}
    Point *p1;
    Point *p2;

    std::vector < Triangle*> triangles;
    EDGE_TYPE type;
    double length_;

    //flows

};



class Contour
{
public:
   std::vector <Point *> points;
   void addPoint(double x, double y, double param)
   {
       points.push_back(new Point(x,y,param,points.size()));
   }
   void addPoint(Point *p) { points.push_back(p); }


   double param;
};



#endif // DATASTRUCTURES_H
